#include "mystdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

MYFILE* my_fopen(const char* filename, const char* mode)
{
    int fd = -1;
    if(strcmp(mode,"w") == 0)
    {
        fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, UMASK);
    }
    else if(strcmp(mode, "r") == 0)
    {
        fd = open(filename, O_RDONLY);
    }
    else if(strcmp(mode, "a") == 0)
    {
        fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, UMASK);
    }
    else if(strcmp(mode, "w+") == 0)
    {
        fd = open(filename, O_CREAT | O_RDWR  | O_TRUNC, UMASK);
    }
    else if(strcmp(mode, "a+") == 0)
    {
        fd = open(filename, O_CREAT | O_RDWR | O_APPEND, UMASK);
    }
    else if(strcmp(mode, "r+") == 0)
    {
        fd = open(filename, O_RDWR, UMASK);
    }
    else{
        return NULL;
    }
    if(fd < 0)
    {
        return NULL;
    }
    MYFILE* fp = (MYFILE*)malloc(sizeof(MYFILE));
    fp->fileno = fd;
    fp->flag = FLUSH_LINE;//这里我们将行刷新写死，目的是为了测试
    fp->cap = SIZE;
    fp->curr = 0;
    fp->outbuffer[0] = 0;//最快清空字符串的方法，把第一个位置设置为\0
    return fp;
}


void my_fclose(MYFILE* fp)
{
    my_fflush(fp);//用户缓冲区刷新到文件内核缓冲区
    fsync(fp->fileno);//文件内核缓冲区刷新到文件
    close(fp->fileno);
    free(fp);
}



static void my_fflush_core(MYFILE* fp, int mode)//强制刷新FORCE和按规则正常刷新NORMAL
{
    if(fp->curr <= 0)
    {
        return;
    }
    if(mode == FORCE)
    {
        write(fp->fileno, fp->outbuffer, fp->curr);
        fp->curr = 0;
    }
    else
    {
        if((fp->flag & FLUSH_LINE) && fp->outbuffer[fp->curr - 1] == '\n')
        {
            write(fp->fileno, fp->outbuffer, fp->curr);
            fp->curr = 0;
        }
        else if((fp->flag & FLUSH_ALL) && fp->curr == fp->cap)
        {
            write(fp->fileno, fp->outbuffer, fp->curr);
            fp->curr = 0;
        }
    }
}


int my_fwrite(const char* ptr, int size, int count, MYFILE* fp)
{
    memcpy(fp->outbuffer + fp->curr, ptr, size*count);
    fp->curr += size * count;
    my_fflush_core(fp, NORMAL);
    return count;
}



void my_fflush(MYFILE* fp)
{
    my_fflush_core(fp, FORCE);
}
